package com.irdstudio.efp.riskm.api.service;

import com.irdstudio.basic.framework.core.cache.Cache;
import com.irdstudio.basic.framework.core.cache.PiccsFrameworkCache;
import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.basic.framework.core.util.BeanUtility;
import com.irdstudio.basic.framework.core.util.SpringContextUtils;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TimeUtil;
import com.irdstudio.basic.framework.core.vo.OrgInfoCacheVO;
import com.irdstudio.basic.framework.core.vo.UserInfoCacheVO;
import com.irdstudio.efp.console.common.ConsoleConstant;
import com.irdstudio.efp.flow.common.constance.FlowConstance;
import com.irdstudio.efp.flow.service.facade.BizFlowEngineInquireService;
import com.irdstudio.efp.flow.service.facade.InstFlowEventService;
import com.irdstudio.efp.flow.service.facade.InstFlowProcessService;
import com.irdstudio.efp.flow.service.vo.InstFlowEventVO;
import com.irdstudio.efp.flow.service.vo.InstFlowProcessVO;
import com.irdstudio.efp.flow.service.vo.PageInquireOutVO;
import com.irdstudio.efp.riskm.service.facade.*;
import com.irdstudio.efp.riskm.service.vo.*;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.irdstudio.basic.framework.core.constant.CacheConstant.CACHE_KEY_ORG_INFOS;
import static com.irdstudio.basic.framework.core.constant.CacheConstant.CACHE_KEY_USER_INFOS;

/**
 * 需求编号【2019D0509】
 * Riskm工程的公用方法服务类
 *
 * @author qiuyf
 * @version 0.1 初始为0.1,后续变更则修改
 * @since 2019/9/26 14:41
 */
@Service("riskmUtilService")
public class RiskmUtilService {

    /**
     * 日志信息
     */
    private final Logger logger = LoggerFactory.getLogger(RiskmUtilService.class);

    @Autowired
    @Qualifier("cooprOrgInfoService")
    private CooprOrgInfoService cooprOrgInfoService;

    @Autowired
    @Qualifier("colltTaskFlowAppService")
    private ColltTaskFlowAppService colltTaskFlowAppService;

    @Autowired
    @Qualifier("colltSmsNoticeAppService")
    private ColltSmsNoticeAppService colltSmsNoticeAppService;

    @Autowired
    @Qualifier("colltDelayCaseRecordService")
    private ColltDelayCaseRecordService colltDelayCaseRecordService;


    @Autowired
    @Qualifier("bizFlowEngineInquireService")
    private BizFlowEngineInquireService bizFlowEngineInquireService;

    @Autowired
    @Qualifier("instFlowProcessService")
    private InstFlowProcessService instFlowProcessService;

    @Autowired
    @Qualifier("instFlowEventService")
    private InstFlowEventService instFlowEventService;



    public final <T> T displayOrgName(T data, String srcColumn, String targetColumn) {
        try {
            // 获取机构缓存
            PiccsFrameworkCache bean = (PiccsFrameworkCache) SpringContextUtils.getBean(Cache.CACHE_BEAN);
            Map<String, OrgInfoCacheVO> orgInfoCacheVOMap = bean.get(CACHE_KEY_ORG_INFOS);
            if (Objects.nonNull(orgInfoCacheVOMap) && Objects.nonNull(data) && StringUtil.isNotEmpty(srcColumn) && StringUtil.isNotEmpty(targetColumn)) {
                if (data instanceof List) {
                    List list = (List) data;
                    for (Object o : list) {
                        String code = StringUtil.replaceObjNull(BeanUtility.getProptery(o, srcColumn));
                        if (StringUtil.isNotEmpty(code)) {
                            Object cacheObject = orgInfoCacheVOMap.get(code);
                            if (Objects.nonNull(cacheObject)) {
                                Object displayName = BeanUtility.getProptery(cacheObject, "orgName");
                                BeanUtility.setProptery(o, targetColumn, displayName);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("当前字段：" + srcColumn + ", 目标字段：" + targetColumn + "转换翻译出现异常!", e);
        }
        return data;
    }

    public final <T> T displayUserName(T data, String srcColumn, String targetColumn) {
        try {
            // 获取机构缓存
            PiccsFrameworkCache bean = (PiccsFrameworkCache) SpringContextUtils.getBean(Cache.CACHE_BEAN);
            Map<String, UserInfoCacheVO> userInfoCacheVOMap = bean.get(CACHE_KEY_USER_INFOS);
            if (Objects.nonNull(userInfoCacheVOMap) && Objects.nonNull(data) && StringUtil.isNotEmpty(srcColumn) && StringUtil.isNotEmpty(targetColumn)) {
                if (data instanceof List) {
                    List list = (List) data;
                    for (Object o : list) {
                        String code = StringUtil.replaceObjNull(BeanUtility.getProptery(o, srcColumn));
                        if (StringUtil.isNotEmpty(code)) {
                            Object cacheObject = userInfoCacheVOMap.get(code);
                            if (Objects.nonNull(cacheObject)) {
                                Object displayName = BeanUtility.getProptery(cacheObject, "userName");
                                BeanUtility.setProptery(o, targetColumn, displayName);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("当前字段：" + srcColumn + ", 目标字段：" + targetColumn + "转换翻译出现异常!", e);
        }
        return data;
    }

    public static String getMarkSaid(int numerrator, int denominator) {
        if (denominator == 0) {
            return null;
        }
        if (numerrator == 0) {
            return String.valueOf(numerrator);
        }
        int maxCommDivNum = getMaxCommDiv(numerrator, denominator);
        return (numerrator / maxCommDivNum) + "/" + (denominator / maxCommDivNum);
    }

    /**
     * 求最大公约数
     *
     * @param n
     * @param d
     * @return
     */
    private static int getMaxCommDiv(int n, int d) {
        if (n < d) {
            int temp = n;
            n = d;
            d = temp;
        }
        int p = n % d;
        while (p != 0) {
            n = d;
            d = p;
            p = n % d;
        }
        return d;
    }

    /**
     * 获取合作状态为"正常"的委外机构 【来自表 coopr_org_info】
     *
     * @return
     */
    public List<CooprOrgInfoVO> getDistrCooprOrgInfos(String cooprOrgType) throws Exception {
        CooprOrgInfoVO cooprOrgInfoVO = new CooprOrgInfoVO();
        cooprOrgInfoVO.setCooprOrgType(cooprOrgType);
        List<CooprOrgInfoVO> result = Optional.ofNullable(cooprOrgInfoService.getAllCooprOrgs(cooprOrgInfoVO))
                .orElseThrow(() -> new Exception("暂无可参与分案的合作机构，请先配置。"));
        return result;
    }


    /**
     * 从HttpServletRequest中获取文件
     *
     * @author
     * @version
     * @since
     */
    @SuppressWarnings("rawtypes")
    public List<File> getFileList(HttpServletRequest request) throws IOException {
        List<File> listFiles = new ArrayList<File>();
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        if (multipartResolver.isMultipart(request)) {
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            Iterator iter = multiRequest.getFileNames();
            while (iter.hasNext()) {
                MultipartFile mFile = multiRequest.getFile(iter.next().toString());
                if (mFile != null) {
                    listFiles.add(multipartToFile(mFile));
                }
            }
        }
        return listFiles;
    }

    /**
     * 转换文件
     *
     * @author
     * @version
     * @since
     */
    private File multipartToFile(MultipartFile multfile) throws IOException {
        CommonsMultipartFile cmf = (CommonsMultipartFile) multfile;
        DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();
        File file = dfi.getStoreLocation();
        if (file.length() < 2048) {
            File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + file.getName());
            multfile.transferTo(tmpFile);
            return tmpFile;
        }
        return file;
    }

    /**
     * 处理人工流转审批中的催收任务
     *
     * @param colltTaskNo 催收任务编号
     */
    public void dealTaskFlowApprIng(String colltTaskNo) throws Exception{
        logger.info("======>强制对催收任务执行撤回，处理人工流转审批中任务开始<======催收任务编号为:" + colltTaskNo);
        try {
            ColltTaskFlowAppVO colltTaskFlowAppVO = new ColltTaskFlowAppVO();
            colltTaskFlowAppVO.setColltTaskNo(colltTaskNo);
            List<ColltTaskFlowAppVO> colltTaskFlowAppVOS = colltTaskFlowAppService.queryByColltTaskNo(colltTaskFlowAppVO);
            if (Objects.isNull(colltTaskFlowAppVOS) || colltTaskFlowAppVOS.isEmpty()) {
                throw new Exception("通过催收任务编号:" + colltTaskNo + "，获取到的人工流转信息为空！");
            }
            //取出审批中的数据，正常只有一笔
            List<ColltTaskFlowAppVO> ctfaVOSResult = colltTaskFlowAppVOS.stream()
                    .filter(ctfaVo -> {
                        return ConsoleConstant.APRV_STATUS_02.equals(ctfaVo.getApproveStatus());
                    })
                    .collect(Collectors.toList());

            if (Objects.nonNull(ctfaVOSResult) && ctfaVOSResult.size() > 0) {
                String flowApplyNo = ctfaVOSResult.get(0).getFlowApplyNo();
                //处理流程
                dealFlowApprInfo(flowApplyNo);
                //更新业务数据
                updColltTaskFlowAppVO(flowApplyNo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("======>强制对催收任务执行撤回，处理人工流转审批中任务失败<======原因为:" + e.getMessage());
            throw e;
        } finally {
            logger.info("======>强制对催收任务执行撤回，处理人工流转审批中任务结束<======催收任务编号为:" + colltTaskNo);
        }
    }


    /**
     * 处理短信通知审批中的催收任务
     *
     * @param colltTaskNo 催收任务编号
     */
    public void dealTaskSmsApprIng(String colltTaskNo) throws Exception{
        logger.info("======>强制对催收任务执行撤回，处理短信通知审批中任务开始<======催收任务编号为:" + colltTaskNo);
        try {
            ColltSmsNoticeAppVO colltSmsNoticeAppVO = new ColltSmsNoticeAppVO();
            colltSmsNoticeAppVO.setColltTaskNo(colltTaskNo);
            List<ColltSmsNoticeAppVO> colltSmsNoticeAppVOS = colltSmsNoticeAppService.queryByColltTaskNo(colltSmsNoticeAppVO);
            if (Objects.isNull(colltSmsNoticeAppVOS) || colltSmsNoticeAppVOS.isEmpty()) {
                throw new Exception("通过催收任务编号:" + colltTaskNo + "，获取到的短信通知申请信息为空！");
            }
            //取出审批中的数据，正常只有一笔
            List<ColltSmsNoticeAppVO> csnaVOResult = colltSmsNoticeAppVOS.stream()
                    .filter(csnaVo -> {
                        return ConsoleConstant.APRV_STATUS_02.equals(csnaVo.getApproveStatus());
                    })
                    .collect(Collectors.toList());

            if (Objects.nonNull(csnaVOResult) && csnaVOResult.size() > 0) {
                String smsNoticeApp = csnaVOResult.get(0).getSmsNoticeApp();
                //处理流程
                dealFlowApprInfo(smsNoticeApp);
                //更新业务数据
                updColltSmsNoticeAppVO(smsNoticeApp);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("======>强制对催收任务执行撤回，处理短信通知审批中任务失败<======原因为:" + e.getMessage());
            throw e;
        } finally {
            logger.info("======>强制对催收任务执行撤回，处理短信通知审批中任务结束<======催收任务编号为:" + colltTaskNo);
        }
    }

    /**
     * 处理延案申请审批中的催收任务
     *
     * @param colltTaskInfoVO 催收任务信息vo
     */
    public void dealTaskDelayApprIng(ColltTaskInfoVO colltTaskInfoVO) throws Exception {
        String colltTaskNo = colltTaskInfoVO.getColltTaskNo();
        String outsOrgCode = colltTaskInfoVO.getOutsOrgCode();
        String colltBatchNo = colltTaskInfoVO.getColltBatchNo();
        logger.info("======>强制对催收任务执行撤回，处理延案申请审批中任务开始<======催收任务编号为:" + colltTaskNo);
        ColltDelayCaseRecordVO colltDelayCaseRecordVO = new ColltDelayCaseRecordVO();
        colltDelayCaseRecordVO.setColltTaskNo(colltTaskNo);
        colltDelayCaseRecordVO.setOutsOrgCode(outsOrgCode);
        colltDelayCaseRecordVO.setColltBatchNo(colltBatchNo);
        int num = colltDelayCaseRecordService.deleteOneVO(colltDelayCaseRecordVO);
        if(num != 1){
            throw new Exception("根据催收任务编号:" +colltTaskNo +",委外机构编号:" +outsOrgCode +",分配批次号:" + colltBatchNo +"，删除委外催收延案记录信息失败");
        }
        logger.info("======>强制对催收任务执行撤回，处理短信通知审批中任务结束<======催收任务编号为:" + colltTaskNo);
    }

    /**
     * 将流程从待办更新为办结
     * @param serno
     * @throws Exception
     */
    private void dealFlowApprInfo(String serno) throws Exception {
        PageInquireOutVO pageInquireOutVO = bizFlowEngineInquireService.waitDoneBySerno(serno);
        if(Objects.nonNull(pageInquireOutVO)){
            String instNodeId = pageInquireOutVO.getInstNodeId();
            //更新表inst_flow_process，处理状态 process_state = 1  和 流转节点状态 inst_node_state = 05
            InstFlowProcessVO instFlowProcessVO = new InstFlowProcessVO();
            instFlowProcessVO.setInstNodeId(instNodeId);
            instFlowProcessVO.setProcessState(FlowConstance.PROCESS_STATE_FINISH);
            instFlowProcessVO.setInstNodeState(FlowConstance.NODE_STATUS_END);
            instFlowProcessVO.setEndTime(TimeUtil.getCurrentDateTime());
            int updNum = instFlowProcessService.updateNodeStatusByInstNodeId(instFlowProcessVO);
            if(updNum <= 0){
                throw new Exception("通过节点实例编号:" + instNodeId + "，更新节点状态失败！");
            }
            //更新表inst_flow_event，业务流转事件状态 biz_event_state == 05
            InstFlowEventVO instFlowEventVO = new InstFlowEventVO();
            instFlowEventVO.setBizSerno(serno);
            instFlowEventVO.setBizEventState(FlowConstance.EVENT_STATUS_END);
            instFlowEventVO.setInstNodeId(instNodeId);
            instFlowEventVO.setEndTime(TimeUtil.getCurrentDateTime());

            updNum = instFlowEventService.updateNodeAndEventStatue(instFlowEventVO);
            if(updNum <= 0){
                throw new Exception("通过业务流水号:" + serno + "，更新事件状态失败！");
            }
        }else{
            throw new Exception("通过业务流水号:" + serno + "，获取到的待办信息为空！");
        }
    }


    public void updColltTaskFlowAppVO(String applyNo){
        ColltTaskFlowAppVO colltTaskFlowAppVO = new ColltTaskFlowAppVO();
        colltTaskFlowAppVO.setFlowApplyNo(applyNo);
        colltTaskFlowAppVO.setApproveStatus(ConsoleConstant.APRV_STATUS_04);
        colltTaskFlowAppVO.setAprvUserCode(BaseConstant.ADMIN);
        colltTaskFlowAppVO.setAprvUserName(BaseConstant.ADMIN);
        colltTaskFlowAppVO.setAprvComment("业务上下游已沟通，对此催收任务执行强制撤回！");
        colltTaskFlowAppVO.setAprvTime(TimeUtil.getCurrentDateTime());
        colltTaskFlowAppVO.setLastUpdateUser(BaseConstant.ADMIN);
        colltTaskFlowAppService.updateByPk(colltTaskFlowAppVO);
    }


    public void updColltSmsNoticeAppVO(String applyNo){
        ColltSmsNoticeAppVO colltSmsNoticeAppVO = new ColltSmsNoticeAppVO();
        colltSmsNoticeAppVO.setSmsNoticeApp(applyNo);
        colltSmsNoticeAppVO.setApproveStatus(ConsoleConstant.APRV_STATUS_04);
        colltSmsNoticeAppVO.setAprvUserCode(BaseConstant.ADMIN);
        colltSmsNoticeAppVO.setAprvUserName(BaseConstant.ADMIN);
        colltSmsNoticeAppVO.setAprvComment("业务上下游已沟通，对此催收任务执行强制撤回！");
        colltSmsNoticeAppVO.setAprvTime(TimeUtil.getCurrentDateTime());
        colltSmsNoticeAppVO.setLastUpdateUser(BaseConstant.ADMIN);
        colltSmsNoticeAppService.updateByPk(colltSmsNoticeAppVO);
    }






}
